﻿
#region Usings
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Transactions;
using System.Windows.Forms;
using FastNET.CleanAct.Client.ManagerEngineBusiness.DataObjects;
using FastNET.CleanAct.Client.ManagerEngineBusiness.ImportExport;
using FastNET.CleanAct.Common.Configuration.Files.PackageExport;
using FastNET.CleanAct.Common.Repository;
using FastNET.CleanAct.Tools.HomeTemplateEditor.ActionDesigners;
using FastNET.CleanAct.Tools.HomeTemplateEditor.Dialogs;
#endregion

namespace FastNET.CleanAct.Tools.HomeTemplateEditor.Forms
{
    internal partial class HomeBox : Form
    {
        #region Variables

        private TreeNode sourceNode;
        private TreeNode templateTreeCurrentDropNode;
        private TreeNode templateTreeLastDropNode;

        #endregion

        #region CTor/DTor

        public HomeBox()
        {
            InitializeComponent();
        }

        #endregion

        #region Form Events

        private void HomeBox_Load(object sender, System.EventArgs e)
        {
            LoadTemplates();
            LoadActions();
        }

        #endregion

        #region Static Calls

        #region Recursive Methods

        private static void AddSubTemplates(Identity parentID, IList<Template> templates, IList<TemplateGroup> groups, TreeNodeCollection root)
        {
            IEnumerable<Identity> childIDs = (from item in groups where item.ParentTemplateID == parentID select item.ChildTemplateID);
            IEnumerable<Template> children = (from item in templates where childIDs.Contains(item.ID) select item);

            foreach (Template template in children)
            {
                TreeNode newNode = AddTemplate(root, template);
                AddSubTemplates(template.ID, templates, groups, newNode.Nodes);
            }
        }

        private static bool IsSubTemplateOf(Identity sourceID, TreeNode childNode)
        {
            if (childNode.Tag == null)
                return false;

            if ((Identity)childNode.Tag == sourceID)
                return true;

            if (childNode.Parent == null || childNode.Parent.Tag == null)
                return false;

            if ((Identity)childNode.Parent.Tag == sourceID)
                return true;

            return IsSubTemplateOf(sourceID, childNode.Parent);
        }

        private static void RenameNodes(Identity sourceID, string newName, TreeNodeCollection children)
        {
            foreach (TreeNode node in children)
            {
                if (node.Tag != null && (Identity)node.Tag == sourceID)
                {
                    node.Text = newName;
                }

                RenameNodes(sourceID, newName, node.Nodes);
            }
        }

        #endregion

        private static TreeNode AddTemplate(TreeNodeCollection root, Template template)
        {
            string imageKey = template.IsBuiltIn ? "built-in" : "basic";

            TreeNode returnValue = root.Add(Guid.NewGuid().ToString(), template.Name, imageKey, imageKey);

            returnValue.Tag = template.ID;

            return returnValue;
        }

        #endregion

        #region Load/Unload

        private void LoadActions()
        {
            ActionList.Items.Clear();
            ActionList.Groups.Clear();

            if (TemplateTreeView.SelectedNode.Tag == null || (Identity)TemplateTreeView.SelectedNode.Tag == new Identity(Guid.Empty))
            {
                return;
            }

            Identity templateID = (Identity)TemplateTreeView.SelectedNode.Tag;

            IEnumerable<TemplateAction> actions = TemplateAction.RetrieveByTemplateID(templateID);

            foreach (TemplateAction action in actions)
            {
                ListViewItem listItem = new ListViewItem { ImageKey = "default", Text = action.Name, Tag = action.ID };

                listItem.SubItems.Add(action.ActionType);
                listItem.SubItems.Add(action.RecursiveMode.ToString());

                //Temporary Grouping System - Should be created in the beginning by available modules
                foreach (ListViewGroup group in ActionList.Groups)
                    if (group.Header.ToLower() == action.ActionType.ToLower())
                        listItem.Group = group;

                if (listItem.Group == null)
                    listItem.Group = ActionList.Groups.Add(action.ActionType, action.ActionType);

                ActionList.Items.Add(listItem);
            }
        }

        private void LoadTemplates()
        {
            IList<Template> templates = Template.Retrieve();
            IList<TemplateGroup> groups = TemplateGroup.Retrieve();

            IEnumerable<Identity> rootChildIDs = (from item in groups where item.ParentTemplateID == Guid.Empty select item.ChildTemplateID);
            IEnumerable<Template> rootTemplates = (from item in templates where rootChildIDs.Contains(item.ID) select item);

            IEnumerable<Identity> childIDs = (from item in groups where item.ParentTemplateID != Guid.Empty select item.ChildTemplateID);

            List<Identity> linkedChildIDs = new List<Identity>();
            foreach (Identity id in from item in groups where item.ParentTemplateID != Guid.Empty select item.ParentTemplateID)
            {
                if (linkedChildIDs.Contains(id))
                {
                    continue;
                }

                linkedChildIDs.Add(id);
            }
            foreach (Identity id in from item in groups select item.ChildTemplateID)
            {
                if (linkedChildIDs.Contains(id))
                {
                    continue;
                }

                linkedChildIDs.Add(id);
            }

            IEnumerable<Template> unlinkedTemplates = (from item in templates where !linkedChildIDs.Contains(item.ID) select item);

            TemplateTreeView.Nodes.Clear();
            TreeNode rootNode = TemplateTreeView.Nodes.Add(Guid.Empty.ToString(), "Root Link", "root", "root");

            rootNode.Tag = new Identity(Guid.Empty);

            foreach (Template template in rootTemplates)
            {
                TreeNode node = AddTemplate(rootNode.Nodes, template);
                AddSubTemplates(template.ID, templates, groups, node.Nodes);
            }

            TemplateTreeView.SelectedNode = rootNode;

            rootNode = TemplateTreeView.Nodes.Add("[Unlinked]", "Unlinked", "root", "root");

            foreach (Template template in unlinkedTemplates)
            {
                TreeNode node = AddTemplate(rootNode.Nodes, template);
                AddSubTemplates(template.ID, templates, groups, node.Nodes);
            }

            TemplateTreeView.ExpandAll();
        }

        #endregion

        #region View Events

        #region Action View

        private void ActionList_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            switch (ActionList.SelectedItems.Count)
            {
                case 1:
                    EditCurrentAction();
                    break;

                case 0:
                    return;

                default:
                    MessageBox.Show(this,
                                    "You can only edit one action at a time",
                                    Text,
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Warning);
                    break;
            }
        }

        #endregion

        #region TemplateTreeView Events

        #region Drag/Drop

        private void TemplateTreeView_ItemDrag(object sender, ItemDragEventArgs e)
        {
            //Begin the drag drop
            sourceNode = (TreeNode)e.Item;
            DoDragDrop(e.Item.ToString(), DragDropEffects.All);
        }

        private void TemplateTreeView_DragEnter(object sender, DragEventArgs e)
        {
            //Validate the data
            e.Effect = e.Data.GetDataPresent(DataFormats.Text) ? DragDropEffects.Move : DragDropEffects.None;
        }

        private void TemplateTreeView_DragDrop(object sender, DragEventArgs e)
        {
            //Get the ID for the source node
            Identity sourceID = (Identity)sourceNode.Tag;

            //Verify that the target is valid
            if (templateTreeCurrentDropNode == null ||
                IsSubTemplateOf(sourceID, templateTreeCurrentDropNode))
            {
                return;
            }

            //Get the parent IDs
            Identity oldParentID = (Identity)(sourceNode.Parent.Tag ?? new Identity(Guid.Empty));
            Identity newParentID = (Identity)(templateTreeCurrentDropNode.Tag ?? new Identity(Guid.Empty));

            try
            {
                //If anything fails, allow us to roll back
                using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required,
                                                                     new TransactionOptions { IsolationLevel = IsolationLevel.RepeatableRead }))
                {
                    try
                    {
                        //If the mode is move, remove the old group
                        if ((e.Effect & DragDropEffects.Move) == DragDropEffects.Move)
                        {
                            TemplateGroup oldGroup = new TemplateGroup(oldParentID, sourceID);
                            oldGroup.Delete();
                        }
                    }
                    catch (InvalidOperationException)
                    {//Cause is unlinked Template
                    }

                    //Create the new group
                    TemplateGroup group = new TemplateGroup { ParentTemplateID = newParentID, ChildTemplateID = sourceID };
                    group.Save();

                    //TODO: Run a try catch and notify of issues
                    scope.Complete();
                }
            }
            catch (Exception)
            {
                MessageBox.Show(this,
                "There was a problem while trying to update the requested Template",
                "Template Update Failed",
                MessageBoxButtons.OK,
                MessageBoxIcon.Stop);
            }

            //Reload the templates
            LoadTemplates();
        }

        private void TemplateTreeView_DragOver(object sender, DragEventArgs e)
        {

            // Determine whether string data exists in the drop data. If not, then
            // the drop effect reflects that the drop cannot occur.
            if (!e.Data.GetDataPresent(DataFormats.Text))
            {
                e.Effect = DragDropEffects.None;
                return;
            }

            //Used for coloring the "target" for drop to make the target a little easier to find
            templateTreeLastDropNode = templateTreeCurrentDropNode;
            templateTreeCurrentDropNode = TemplateTreeView.GetNodeAt(TemplateTreeView.PointToClient(new Point(e.X, e.Y)));

            //If the selection has not changed, just return
            if (templateTreeLastDropNode == templateTreeCurrentDropNode)
            {
                return;
            }

            //If there was a previous node highlighted, reset it
            if (templateTreeLastDropNode != null)
            {
                templateTreeLastDropNode.ForeColor = TemplateTreeView.ForeColor;
                templateTreeLastDropNode.BackColor = Color.Transparent;
            }

            //Color the new target
            templateTreeCurrentDropNode.ForeColor = SystemColors.HighlightText;
            templateTreeCurrentDropNode.BackColor = SystemColors.HotTrack;

            //Expand the highlighted node
            templateTreeCurrentDropNode.Expand();

            //Verify the node is not the unlinked group
            if (templateTreeCurrentDropNode.Tag == null)
            {
                e.Effect = DragDropEffects.None;
                return;
            }

            //Verify the node isn't going to be under it's old position
            if (IsSubTemplateOf((Identity)sourceNode.Tag, templateTreeCurrentDropNode))
            {
                e.Effect = DragDropEffects.None;
                return;
            }

            //Verify the same node does not exist in the new target already
            foreach (TreeNode node in templateTreeCurrentDropNode.Nodes)
            {
                if ((Identity)sourceNode.Tag != (Identity)node.Tag)
                {
                    continue;
                }

                e.Effect = DragDropEffects.None;
                return;
            }

            //Pick the action based on the key being pressed
            if ((e.KeyState & 8) == 8 && (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy)
            {
                e.Effect = DragDropEffects.Copy;
            }
            else
            {
                e.Effect = (e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move ? DragDropEffects.Move : DragDropEffects.None;
            }
        }

        #endregion

        #region Label Editing

        private void TemplateTreeView_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            if (e.Node.Tag != null && (Identity)e.Node.Tag != new Identity(Guid.Empty))
            {
                return;
            }

            e.CancelEdit = true;
        }

        private void TemplateTreeView_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            if (e.Node == null || e.Node.Tag == null || (Identity)e.Node.Tag == new Identity(Guid.Empty) || string.IsNullOrEmpty(e.Label))
            {
                e.CancelEdit = true;
                return;
            }

            Template template = new Template((Identity)e.Node.Tag) { Name = e.Label };

            template.Save();

            //We must update names instead of reloading because of strange issues with this event
            RenameNodes((Identity)e.Node.Tag, e.Label, TemplateTreeView.Nodes);
        }

        #endregion

        private void TemplateTreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (TemplateTreeView.SelectedNode == null || TemplateTreeView.SelectedNode.Tag == null ||
                (Identity)TemplateTreeView.SelectedNode.Tag == new Identity(Guid.Empty))
            {
                TemplateTitle.Text = e.Node.Text;
                PackageInfoPanel.Visible = false;
                PackageName.Visible = false;
                return;
            }

            PackageInfoPanel.Visible = true;
            PackageName.Visible = true;

            TemplateTitle.Text = e.Node.Text;

            Identity templateID = (Identity)TemplateTreeView.SelectedNode.Tag;

            Template template = new Template(templateID);

            if (template.PackageID.HasValue)
            {
                Package package = new Package(template.PackageID.Value);

                PackagePublisher.Text = package.Publisher;
                PackageVersion.Text = package.Version.ToString();
                PackageName.Text = package.Name;
            }
            else
            {
                PackageInfoPanel.Visible = false;
                PackageName.Text = "User Created";
            }

            LoadActions();
        }

        #endregion

        #endregion

        #region Resource Management

        #region Template Management

        private void EditTemplate()
        {
            if (TemplateTreeView.SelectedNode == null || TemplateTreeView.SelectedNode.Tag == null)
            {
                return;
            }

            Template template = new Template((Identity)TemplateTreeView.SelectedNode.Tag);
            TemplateBox form = new TemplateBox
                               {
                                   PackageID = template.PackageID,
                                   IsBuiltIn = template.IsBuiltIn,
                                   TemplateName = template.Name
                               };

            if (form.ShowDialog() == DialogResult.Cancel)
                return;

            template.PackageID = form.PackageID;
            template.IsBuiltIn = form.IsBuiltIn;
            template.Name = form.TemplateName;
            template.Save();

            LoadTemplates();
        }

        private void CreateTemplate()
        {
            TemplateBox form = new TemplateBox();
            if (form.ShowDialog() == DialogResult.Cancel)
                return;

            //If anything fails, allow us to roll back
            using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required,
                                                                 new TransactionOptions { IsolationLevel = IsolationLevel.RepeatableRead }))
            {
                Template newTemplate = new Template { IsBuiltIn = form.IsBuiltIn, Name = form.TemplateName, PackageID = form.PackageID };
                newTemplate.Save();

                TemplateGroup newGroup = new TemplateGroup { ChildTemplateID = newTemplate.ID };
                if (TemplateTreeView.SelectedNode != null &&
                    TemplateTreeView.SelectedNode.Tag != null)
                {
                    newGroup.ParentTemplateID = (Identity)TemplateTreeView.SelectedNode.Tag;
                }
                else
                {
                    newGroup.ParentTemplateID = Guid.Empty;
                }
                newGroup.Save();

                scope.Complete();
            }

            LoadTemplates();
        }

        private void DeleteSelectedTemplate()
        {
            if (TemplateTreeView.SelectedNode == null || TemplateTreeView.SelectedNode.Tag == null ||
                (Identity)TemplateTreeView.SelectedNode.Tag == new Identity(Guid.Empty))
            {
                return;
            }

            if (MessageBox.Show(this, "Are you sure you want to delete this entry? This process cannot be reversed.", "Confirm Deletion",
                MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.No)
            {
                return;
            }

            try
            {
                //If anything fails, allow us to roll back
                using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required,
                                                                     new TransactionOptions { IsolationLevel = IsolationLevel.RepeatableRead }))
                {
                    Template template = new Template((Identity)TemplateTreeView.SelectedNode.Tag);

                    template.Delete();

                    //TODO: Run a try catch and notify of issues
                    scope.Complete();
                }
            }
            catch (Exception)
            {
                MessageBox.Show(this,
                                "There was a problem while trying to delete the requested Template",
                                "Template Delete Failed",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Stop);
            }

            LoadTemplates();
        }

        private void SelectBuiltInTemplate()
        {
            if (TemplateTreeView.SelectedNode == null || TemplateTreeView.SelectedNode.Tag == null)
            {
                return;
            }

            Template template = new Template((Identity)TemplateTreeView.SelectedNode.Tag);

            template.IsBuiltIn = !template.IsBuiltIn;

            template.Save();

            LoadTemplates();
        }

        private void LinkTemplates()
        {
            SelectTemplate frm = new SelectTemplate
            {
                SourceID = ((Identity)TemplateTreeView.SelectedNode.Tag)
            };

            if (frm.ShowDialog(this) == DialogResult.Cancel)
            {
                return;
            }

            if (frm.DestinationID.HasValue)
            {
                //Create the new group
                TemplateGroup group = new TemplateGroup { ParentTemplateID = frm.DestinationID.Value, ChildTemplateID = ((Identity)TemplateTreeView.SelectedNode.Tag) };
                group.Save();
            }
            else
            {
                //Create the new group
                TemplateGroup group = new TemplateGroup { ParentTemplateID = new Identity(Guid.Empty), ChildTemplateID = ((Identity)TemplateTreeView.SelectedNode.Tag) };
                group.Save();
            }

            LoadTemplates();
        }

        private void UnlinkTemplates()
        {
            if (TemplateTreeView.SelectedNode == null || TemplateTreeView.SelectedNode.Tag == null)
            {
                return;
            }

            //Get the parent IDs
            Identity oldParentID = (Identity)(TemplateTreeView.SelectedNode.Parent.Tag ?? new Identity(Guid.Empty));

            TemplateGroup oldGroup = new TemplateGroup(oldParentID, (Identity)TemplateTreeView.SelectedNode.Tag);

            oldGroup.Delete();

            LoadTemplates();
        }

        #endregion

        #region Action Management

        private void RemoveAction()
        {
            if (ActionList.SelectedItems.Count <= 0)
                return;

            if (MessageBox.Show(this, "Are you sure you want to permenantly remove the selected items from the database?", "Delete Confirmation",
                MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.No)
                return;

            foreach (ListViewItem item in ActionList.SelectedItems)
            {
                TemplateAction action = new TemplateAction((Identity)item.Tag);
                action.Delete();
            }

            LoadActions();
        }

        private void NewAction()
        {
            if (TemplateTreeView.SelectedNode.Tag == null || (Identity)TemplateTreeView.SelectedNode.Tag == new Identity(Guid.Empty))
            {
                return;
            }

            RegistryActionCreator frm = new RegistryActionCreator();

            Identity templateID = (Identity)TemplateTreeView.SelectedNode.Tag;
            TemplateAction action = new TemplateAction();

            if (frm.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            action.TemplateID = templateID;
            action.Name = frm.ActionName;
            action.RecursiveMode = frm.ActionRecursiveMode;
            action.Pattern = frm.ActionValue;
            action.ActionType = "Registry";

            action.Save();

            LoadActions();
        }

        private void EditCurrentAction()
        {
            if (ActionList.SelectedItems.Count <= 0 || ActionList.SelectedItems[0].Tag == null)
            {
                return;
            }

            RegistryActionCreator frm = new RegistryActionCreator();

            Identity actionID = (Identity)ActionList.SelectedItems[0].Tag;
            TemplateAction action = new TemplateAction(actionID);

            frm.ActionName = action.Name;
            frm.ActionRecursiveMode = action.RecursiveMode;
            frm.ActionValue = action.Pattern;

            if (frm.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            action.Name = frm.ActionName;
            action.RecursiveMode = frm.ActionRecursiveMode;
            action.Pattern = frm.ActionValue;

            action.Save();

            LoadActions();
        }

        #endregion

        #endregion

        #region Menus

        #region File Menu

        private void FileManagePackage_Click(object sender, EventArgs e)
        {
            PackageBox packageBox = new PackageBox();

            packageBox.ShowDialog(this);
        }

        private void FileExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void FileExport_Click(object sender, EventArgs e)
        {
            SelectPackage selectPackage = new SelectPackage();
            ExportDialog.Filter = "CleanAct Package|*.capkg|CleanAct Signed Package|*.caspkg|All Files|*.*";

            if (selectPackage.ShowDialog(this) == DialogResult.Cancel)
            {
                return;
            }

            if (!selectPackage.SelectedPackage.HasValue)
            {
                return;
            }

            if (ExportDialog.ShowDialog(this) == DialogResult.Cancel)
            {
                return;
            }



            //TODO: Make the file!



            switch (ExportDialog.FilterIndex)
            {
                case 1:
                case 3:
                    PackageUtil.ExportPackage(ExportDialog.FileName, selectPackage.SelectedPackage.Value);
                    break;
                case 2:
                    X509Store store = new X509Store(StoreLocation.CurrentUser);
                    store.Open(OpenFlags.ReadOnly);

                    X509Certificate2Collection fcollection = store.Certificates;
                    //fcollection = fcollection.Find(X509FindType.FindByTimeValid, DateTime.Now, true);
                    //fcollection = fcollection.Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, true);


                    fcollection = X509Certificate2UI.SelectFromCollection(fcollection,
                                                            "Package Signing Certificate",
                                                            "Please select a certificate from your personal store to sign the package with",
                                                            X509SelectionFlag.SingleSelection,
                                                            Handle);

                    if (fcollection.Count <= 0)
                    {
                        return;
                    }

                    if (!fcollection[0].HasPrivateKey)
                    {
                        MessageBox.Show(this,
                                        "The selected certificate cannot be used because a private key cannot be found to sign with",
                                        "Invalid Certificate",
                                        MessageBoxButtons.OK,
                                        MessageBoxIcon.Stop);
                        return;
                    }

                    PackageUtil.ExportSignedPackage(ExportDialog.FileName, selectPackage.SelectedPackage.Value, fcollection[0]);
                    PackageUtil.UnsignPackage(ExportDialog.FileName);
                    break;
                default:

                    break;
            }
        }

        private void FileImport_Click(object sender, EventArgs e)
        {
            ImportDialog.Filter = "CleanAct Package|*.capkg|CleanAct Signed Package|*.caspkg|All Files|*.*";

            if (ImportDialog.ShowDialog(this) == DialogResult.Cancel)
            {
                return;
            }

            foreach (string fileName in ImportDialog.FileNames)
            {
                ExportPackageSettings settings;

                switch (ImportDialog.FilterIndex)
                {
                    case 1:
                    case 3:
                        settings = ExportPackageSettings.Load(fileName);
                        break;
                    case 2:
                        PackageUtil.UnsignResult result = PackageUtil.UnsignPackage(fileName);

                        if (!result.Certificate.Verify())
                        {
                            ValidateCertDialog dlg = new ValidateCertDialog { Certificate = result.Certificate, FileName = fileName };

                            if (dlg.ShowDialog(this) == DialogResult.No)
                            {
                                continue;
                            }
                        }


                        if (result.Settings != null)
                        {
                            settings = result.Settings;
                        }
                        else
                        {
                            MessageBox.Show(this,
                                            String.Format(
                                                "The file {0} contains an invalid signature and will not be imported.",
                                                fileName),
                                            "Invalid Signature",
                                            MessageBoxButtons.OK,
                                            MessageBoxIcon.Stop);
                            continue;
                        }
                        break;
                    default:
                        continue;
                }

                if (Package.CheckNameExists(settings.PackageInfo.Name))
                {
                    if (MessageBox.Show(this, "The package \"" + settings.PackageInfo.Name + "\" currently exists. Do you want to remove the old package and all associated data?",
                        "Package Exists", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.No)
                    {
                        continue;
                    }

                    PackageUtil.RemoveOldPackage(settings.PackageInfo.Name);
                }

                PackageUtil.ImportPackage(settings);
            }

            LoadTemplates();
        }

        #endregion

        #region Template Tree Menu

        private void TreeMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (TemplateTreeView.SelectedNode.Tag == null || (Identity)TemplateTreeView.SelectedNode.Tag == new Identity(Guid.Empty))
            {
                TreeRemove.Visible = false;
                TreeEdit.Visible = false;
                TreeUnlink.Visible = false;
                TreeLink.Visible = false;
                TreeSeparator1.Visible = false;
                TreeSeparator2.Visible = false;
                TreeBuiltIn.Visible = false;
                return;
            }

            TreeRemove.Visible = true;
            TreeEdit.Visible = true;
            TreeUnlink.Visible = true;
            TreeLink.Visible = true;
            TreeSeparator1.Visible = true;
            TreeSeparator2.Visible = true;
            TreeBuiltIn.Visible = true;

            Template selectedTemplate = new Template((Identity)TemplateTreeView.SelectedNode.Tag);

            TreeBuiltIn.Checked = selectedTemplate.IsBuiltIn;
            TreeUnlink.Enabled = true;
            TreeLink.Enabled = true;
        }

        private void TreeBuiltIn_Click(object sender, EventArgs e)
        {
            SelectBuiltInTemplate();
        }

        private void TreeAdd_Click(object sender, EventArgs e)
        {
            CreateTemplate();
        }

        private void TreeEdit_Click(object sender, EventArgs e)
        {
            EditTemplate();
        }

        private void TreeRemove_Click(object sender, EventArgs e)
        {
            DeleteSelectedTemplate();
        }

        private void TreeLink_Click(object sender, EventArgs e)
        {
            LinkTemplates();
        }

        private void TreeUnlink_Click(object sender, EventArgs e)
        {
            UnlinkTemplates();
        }

        #endregion

        #region Template Menu

        private void Templates_DropDownOpening(object sender, EventArgs e)
        {
            if (TemplateTreeView.SelectedNode == null || TemplateTreeView.SelectedNode.Tag == null ||
                (Identity)TemplateTreeView.SelectedNode.Tag == new Identity(Guid.Empty))
            {
                TemplatesRemove.Enabled = false;
                TemplatesUnlink.Enabled = false;
                TemplatesLink.Enabled = false;
                TemplatesEdit.Enabled = false;
            }
            else
            {
                TemplatesRemove.Enabled = true;
                TemplatesLink.Enabled = true; //Feature from menu is not implemented right now
                TemplatesUnlink.Enabled = true;
                TemplatesEdit.Enabled = true;
            }
        }

        private void TemplatesAdd_Click(object sender, EventArgs e)
        {
            CreateTemplate();
        }

        private void TemplatesEdit_Click(object sender, EventArgs e)
        {
            EditTemplate();
        }

        private void TemplatesRemove_Click(object sender, EventArgs e)
        {
            DeleteSelectedTemplate();
        }

        private void TemplatesLink_Click(object sender, EventArgs e)
        {
            LinkTemplates();
        }

        private void TemplatesUnlink_Click(object sender, EventArgs e)
        {
            UnlinkTemplates();
        }

        #endregion

        #region Actions Menu

        private void Actions_DropDownOpening(object sender, EventArgs e)
        {
            ActionsRemove.Enabled = (ActionList.SelectedItems.Count > 0);
            ActionsEdit.Enabled = (ActionList.SelectedItems.Count == 1);
            ActionsAdd.Enabled = (TemplateTreeView.SelectedNode != null && TemplateTreeView.SelectedNode.Tag != null &&
                                  (Identity)TemplateTreeView.SelectedNode.Tag != new Identity(Guid.Empty));
        }

        private void ActionsRemove_Click(object sender, EventArgs e)
        {
            RemoveAction();
        }

        private void ActionsEdit_Click(object sender, EventArgs e)
        {
            EditCurrentAction();
        }

        private void ActionsAddRegistry_Click(object sender, EventArgs e)
        {
            NewAction();
        }

        #endregion

        #region Help Menu

        private void HelpAbout_Click(object sender, System.EventArgs e)
        {
            AboutBox form = new AboutBox();

            form.ShowDialog(this);
        }

        #endregion

        private void TemplateTreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                TemplateTreeView.SelectedNode = e.Node;
            }
        }

        #endregion
    }
}